-
Notifications
You must be signed in to change notification settings - Fork 114
Fixes nested dependency detection in NpmLockfile3Detector and applies the engines array fix that was missing from PR #1400. #1606
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…cation - Rewrite ProcessLockfile to iterate ALL packages directly instead of tree traversal - Add node-style module resolution for dependency graph edges - Fix devOptional and peer+dev dependencies to be classified as dev dependencies - Skip link packages (symbolic links) and bundled dependencies - Handle engines field as JsonElement to support both object and array formats - Add tests for devOptional, peer-only, and engines-as-array scenarios Fixes issue microsoft#1380 ## Test Results Tested against multiple real-world repositories with npm lockfile v3: - Main branch crashes when engines field is array format instead of object - This PR correctly handles both object and array formats for engines - This PR detects all packages from lockfile including nested dependencies - NpmLockfile3 now finds the complete transitive dependency tree
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1606 +/- ##
=======================================
+ Coverage 90.1% 90.2% +0.1%
=======================================
Files 437 437
Lines 37431 38027 +596
Branches 2316 2342 +26
=======================================
+ Hits 33736 34319 +583
+ Misses 3221 3219 -2
- Partials 474 489 +15 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes nested dependency detection in NpmLockfile3Detector and applies the missing engines array converter fix from PR #1400. The core change rewrites the ProcessLockfile method from a queue-based traversal to a cleaner three-pass approach that processes all packages directly, then registers components, and finally builds dependency edges using node-style module resolution.
Key changes:
- Replaces complex queue-based dependency traversal with direct iteration over all packages in lockfile
- Implements node-style module resolution for dependency graph construction, walking up the directory tree to find dependencies
- Fixes devOptional classification to correctly mark peer dependencies that are also dev dependencies
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/Microsoft.ComponentDetection.Detectors/npm/NpmLockfile3Detector.cs | Complete rewrite of ProcessLockfile to use three-pass approach with node-style resolution; removes queue-based traversal |
| src/Microsoft.ComponentDetection.Detectors/npm/NpmLockfileDetectorBase.cs | Adds new RecordComponent overload for registering components with explicit reference flag |
| src/Microsoft.ComponentDetection.Detectors/npm/Contracts/PackageLockV3Package.cs | Applies PackageJsonEnginesConverter to Engines property to handle array format |
| test/Microsoft.ComponentDetection.Detectors.Tests/NpmLockfile3DetectorTests.cs | Adds three new tests for devOptional, peer, and engines array handling |
| test/Microsoft.ComponentDetection.Detectors.Tests/NpmTestUtilities.cs | Adds helper methods for generating test lockfiles with devOptional and peer dependencies |
src/Microsoft.ComponentDetection.Detectors/npm/NpmLockfileDetectorBase.cs
Show resolved
Hide resolved
…ng and handling of link/bundled packages
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
src/Microsoft.ComponentDetection.Detectors/npm/NpmLockfile3Detector.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.ComponentDetection.Detectors/npm/NpmLockfile3Detector.cs
Outdated
Show resolved
Hide resolved
| // The shared dependency appears in both dev and non-dev contexts, so should NOT be marked as dev | ||
| var sharedDep = detectedComponents.First(x => ((NpmComponent)x.Component).Name.Equals(sharedDepName)); | ||
| componentRecorder.GetEffectiveDevDependencyValue(sharedDep.Component.Id).Should().BeFalse(); |
Copilot
AI
Jan 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test comment states "The shared dependency appears in both dev and non-dev contexts," but the lockfile structure shows the shared dependency appears only once at "node_modules/{4}" without a dev flag. The multi-path dev status tracking logic (lines 135-138 in NpmLockfile3Detector.cs) is not actually exercised by this test since the component appears at only one path in the lockfile. Consider adding a test case where the same component (name + version) appears at multiple different paths in the lockfile with different dev flags to properly test the multi-path logic.
src/Microsoft.ComponentDetection.Detectors/npm/NpmLockfile3Detector.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.ComponentDetection.Detectors/npm/NpmLockfileDetectorBase.cs
Outdated
Show resolved
Hide resolved
|
@copilot open a new pull request to apply changes based on the comments in this thread |
…ector.cs Co-authored-by: Copilot <[email protected]>
…ector.cs Co-authored-by: Copilot <[email protected]>
…ector.cs Co-authored-by: Copilot <[email protected]>
…ctorBase.cs Co-authored-by: Copilot <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
|
|
||
| // Build package lookup - keys are paths like "node_modules/lodash" or "node_modules/a/node_modules/b" | ||
| // Collect direct dependencies from package.json for explicit reference tracking | ||
| var directDependencies = new HashSet<string>(System.StringComparer.Ordinal); |
Copilot
AI
Jan 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NPM package names are case-sensitive according to the npm specification. Using StringComparer.OrdinalIgnoreCase could lead to incorrect matching of package names. For example, "React" and "react" would be treated as the same package when they are actually different. This should be changed to StringComparer.Ordinal to ensure case-sensitive matching.
Changes
ProcessLockfileto iterate ALL packages directly (matching npm's actual behavior)PackageJsonEnginesConvertertoPackageLockV3Package.Engines(PR don't throw ifenginesproperty is a string array #1400 only fixedNpmComponentDetector, notNpmLockfile3Detector)Testing